﻿#pragma execution_character_set("utf-8")

#include "attitudeindicator.h"
#include "qpainter.h"
#include <QPainterPath>
#include "qmath.h"
#include "qdebug.h"

AttitudeIndicator::AttitudeIndicator(QWidget *parent) : QWidget(parent)
{
    borderOutColorStart = QColor(180, 180, 180);
    borderOutColorEnd = QColor(175, 207, 255);

    borderInColorStart = QColor(50, 50, 50);
    borderInColorEnd = QColor(220, 220, 220);
    bgOutColor = QColor(33, 33, 33);
    foreground = QColor(255, 255, 255);

    bgUpperColor = QColor(41, 127, 184, 150);
    bgLowerColor = QColor(150, 108, 62, 150);
    glassColor = QColor(250, 250, 250);
    scaleColor = QColor(255, 255, 255);
    lineColor = QColor(255, 255, 255);
    textColor = QColor(255, 255, 255);
    pointerColor = QColor(254, 215, 0);
    pointerOutColor = QColor(255, 107, 107);
    handleColor = QColor(254, 215, 0);
    darkColor = QColor(51, 60, 75);
    lightColor = QColor(109, 134, 162);

    rollValue = 0;
    pitchValue = 0;
}

void AttitudeIndicator::paintEvent(QPaintEvent *)
{
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    painter.translate(width / 2, height / 2);
    painter.scale(side / 200.0, side / 200.0);

    //绘制背景
    drawBg(&painter);
    //绘制姿势仪背景和水平航向刻度线
    drawPlane(&painter);
    //绘制玻璃遮罩层
    drawGlass(&painter);
    //绘制刻度尺
    drawScale(&painter);
    //绘制线条
    drawLine(&painter);
    //绘制指针
    drawPointer(&painter);
    //绘制手柄
    drawHandle(&painter);
    ////////////////////////////////////////
    //绘制外边框
    drawBorderOut(&painter);
    //绘制外侧黑色背景
    drawBgOut(&painter);
    //绘制外侧刻度
    drawScaleOut(&painter);
    //绘制东南西北标识
    drawScaleOutNum(&painter);
    //绘制外部指针
    drawPointerOut(&painter);
}

void AttitudeIndicator::drawBorderOut(QPainter *painter)
{
    int outerRadius = 100;
    int innerRadius = 94;

    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(borderOutColorEnd);

    QPainterPath path;
    path.addEllipse(QPointF(0, 0), outerRadius, outerRadius);
    path.addEllipse(QPointF(0, 0), innerRadius, innerRadius);
    painter->drawPath(path);
    painter->restore();
}

void AttitudeIndicator::drawBgOut(QPainter *painter)
{
    int outerRadius = 94;
    int innerRadius = 75;

    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(bgOutColor);

    QPainterPath path;
    path.addEllipse(QPointF(0, 0), outerRadius, outerRadius);
    path.addEllipse(QPointF(0, 0), innerRadius, innerRadius);
    painter->drawPath(path);
    painter->restore();
}

void AttitudeIndicator::drawBg(QPainter *painter)
{
    int radius = 75;
    // int radius = 90;
    painter->save();
    painter->setPen(Qt::NoPen);
    QLinearGradient borderGradient(0, -radius, 0, radius);
    borderGradient.setColorAt(0, bgLowerColor);
    borderGradient.setColorAt(1, bgLowerColor);
    painter->setBrush(borderGradient);
    painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);

    painter->restore();
}
void AttitudeIndicator::drawPlane(QPainter *painter)
{
    // 使用与刻度线相同的参数确保对齐
    const double DEGREES_TO_PIXELS = 1.8;  // 角度到像素的转换系数（与刻度线一致）

    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);
    // int radius = side / 2;
    int radius = 100;

    painter->save();

    // 坐标系设置 - 与刻度线完全一致
    // painter->resetTransform();
    // painter->translate(width / 2, height / 2);  // 中心点
    // painter->scale(side / 200.0, side / 200.0); // 标准化坐标系
    painter->rotate(rollValue);                 // 只旋转横滚角

    // 计算地平线位置（关键：使用与刻度线相同的计算）
    double horizonY = pitchValue * DEGREES_TO_PIXELS;

    // 设置剪裁区域为圆形
    QPainterPath clipPath;
    clipPath.addEllipse(QRectF(-radius, -radius, radius*2, radius*2));
    painter->setClipPath(clipPath);

    // 计算天空和地面的矩形区域
    double skyHeight = radius + horizonY;  // 天空高度
    double groundHeight = radius - horizonY; // 地面高度

    // 确保高度不为负值
    if (skyHeight < 0) skyHeight = 0;
    if (groundHeight < 0) groundHeight = 0;

    // 绘制天空（蓝色）
    painter->setPen(Qt::NoPen);
    painter->setBrush(bgUpperColor); // 天空蓝
    painter->drawRect(QRectF(-radius, -radius, radius*2, skyHeight));

    // 绘制地面（黄色）
    painter->setBrush(bgLowerColor); // 大地黄
    painter->drawRect(QRectF(-radius, -radius + skyHeight, radius*2, groundHeight));

    // 绘制地平线（蓝黄分界线）
    QPen horizonPen(Qt::black, 2.5);
    painter->setPen(horizonPen);
    painter->drawLine(QPointF(-radius, horizonY), QPointF(radius, horizonY));

    // === 添加航向刻度（水平滚动）===
    // 航向刻度参数
    const double PIXELS_PER_DEGREE = 1.8;  // 角度到像素的转换系数
    const int MARK_SPACING = 10;           // 刻度间距（度）
    const int MAJOR_INTERVAL = 30;         // 主刻度间隔（度）
    const double MARK_Y_OFFSET = 0;     // 刻度线Y轴偏移（地平线下方）
    const int MINOR_MARK_LENGTH = 6;       // 短刻度长度
    const int MAJOR_MARK_LENGTH = 12;      // 长刻度长度
    const int TEXT_OFFSET = 20;            // 文本偏移量

    // 设置刻度线样式
    QPen headingPen(Qt::white, 1);
    painter->setPen(headingPen);

    // 准备文本绘制
    QFont font = painter->font();
    font.setPointSize(8);
    painter->setFont(font);

    // 计算可见的航向范围（基于当前yawValue）
    double visibleRange = radius * 2.0 / PIXELS_PER_DEGREE;
    double startYaw = yawValue - visibleRange / 2.0;
    double endYaw = yawValue + visibleRange / 2.0;

    // 绘制刻度线和文本
    for (int deg = static_cast<int>(std::floor(startYaw / MARK_SPACING)) * MARK_SPACING;
         deg <= endYaw;
         deg += MARK_SPACING) {

        // 规范化角度到[0, 360)
        int normalizedDeg = (deg % 360 + 360) % 360;

        // 计算刻度位置（水平滚动效果）
        double xPos = (deg - yawValue) * PIXELS_PER_DEGREE;

        // 只绘制在可见区域内的刻度
        if (xPos < -radius || xPos > radius) continue;

        // 确定刻度类型（主/次）
        bool isMajor = (normalizedDeg % MAJOR_INTERVAL == 0);
        int markLength = isMajor ? MAJOR_MARK_LENGTH : MINOR_MARK_LENGTH;

        // 绘制刻度线（地平线下方）
        double markY = horizonY + MARK_Y_OFFSET;
        painter->drawLine(QPointF(xPos, markY),
                          QPointF(xPos, markY + markLength));

        // 绘制主刻度文本
        if (isMajor) {
            // 保存当前变换状态
            painter->save();

            // 重置坐标系（移除旋转变换）
            painter->resetTransform();
            painter->translate(width / 2, height / 2);
            painter->scale(side / 200.0, side / 200.0);

            // 计算文本位置（考虑横滚角的影响）
            double cr = cos(rollValue * M_PI / 180.0);
            double sr = sin(rollValue * M_PI / 180.0);
            double textX = xPos * cr - (markY + markLength + 2) * sr;
            double textY = xPos * sr + (markY + markLength + 2) * cr;

            // 绘制文本（确保水平显示）
            QRectF textRect(textX - 20, textY - 12, 40, 12);
            painter->drawText(textRect, Qt::AlignCenter, QString::number(normalizedDeg));

            // 恢复变换状态
            painter->restore();
        }
    }

    painter->restore();
}
void AttitudeIndicator::drawGlass(QPainter *painter)
{
    int radius = 60;
    // int radius = 80;
    painter->save();
    painter->setPen(Qt::NoPen);

    //饼圆1为整个圆形区域
    QRect pieRect1(-radius, -radius, radius * 2, radius * 2);
    //饼圆2位饼圆1区域的中间部分的四分之一
    QRect pieRect2(-radius, -radius / 4, radius * 2, radius / 4 * 2);

    //颜色线性渐变,颜色透明度产生立体感
    QLinearGradient linearGradient(pieRect1.topLeft(), pieRect1.bottomRight());
    glassColor.setAlpha(30);
    linearGradient.setColorAt(0.1, glassColor);
    glassColor.setAlpha(100);
    linearGradient.setColorAt(0.5, glassColor);

    //绘制两个饼圆
    painter->setBrush(linearGradient);
    painter->drawPie(pieRect1, 0, 16 * 180);
    painter->drawPie(pieRect2, 0, -16 * 180);

    painter->restore();
}

void AttitudeIndicator::drawScale(QPainter *painter)
{
    int radius = 73;
    // int radius = 88;
    painter->save();

    //设置画笔颜色
    QPen pen;
    pen.setColor(scaleColor);
    pen.setWidthF(4);
    pen.setCapStyle(Qt::RoundCap);
    painter->setPen(pen);

    //左侧平行线
    painter->rotate(90);
    painter->drawLine(0, radius - 4, 0, radius);

    //逐个绘制大刻度
    for (int i = 0; i < 6; i++) {
        painter->rotate(30);
        painter->drawLine(0, radius - 4, 0, radius);
    }

    //回到小刻度,重新设置画笔宽度
    pen.setWidthF(2);
    painter->setPen(pen);
    painter->rotate(-180);

    //逐个绘制小刻度
    for (int i = 0; i < 17; i++) {
        painter->rotate(10);
        painter->drawLine(0, radius - 3, 0, radius);
    }

    painter->restore();
}

void AttitudeIndicator::drawLine(QPainter *painter)
{
    // 可配置参数（建议设为类成员变量）
    const int LINE_INTERVAL = 10;          // 刻度间隔（度）
    const int VISIBLE_RANGE = 40;          // 单侧可见范围（度）
    const double BASE_LENGTH = 25.0;       // 0度线基准长度
    const double LENGTH_INCREMENT = 5.0;   // 每10度长度增量
    const double DEGREES_TO_PIXELS = 1.8;  // 角度到像素的转换系数

    painter->save();

    // 坐标系设置 - 只处理横滚
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);
    painter->resetTransform();
    painter->translate(width / 2, height / 2);
    painter->scale(side / 200.0, side / 200.0);
    painter->rotate(rollValue);

    // 设置画笔
    QPen pen(lineColor);
    pen.setWidthF(1.5);
    pen.setCapStyle(Qt::RoundCap);
    painter->setPen(pen);

    // 设置字体和精确度量
    QFont font;
    font.setPixelSize(10);
    font.setBold(true);
    painter->setFont(font);
    QFontMetricsF fm(font); // 使用浮点版本确保精度

    // 预计算文本偏移量（避免重复计算）
    const double TEXT_OFFSET = 8.0; // 文本与刻度的固定间距

    // 计算可见范围（对齐到刻度间隔）
    int centerDeg = qRound(pitchValue / LINE_INTERVAL) * LINE_INTERVAL;
    int minDeg = qMax(centerDeg - VISIBLE_RANGE, -90);
    int maxDeg = qMin(centerDeg + VISIBLE_RANGE, 90);

    // 绘制刻度线
    for (int deg = minDeg; deg <= maxDeg; deg += LINE_INTERVAL) {
        // 计算刻度线的垂直位置
        double yPos = (pitchValue - deg) * DEGREES_TO_PIXELS;

        // 跳过超出可见区域的刻度
        if (qAbs(yPos) > 100) continue;

        // 计算线长（随角度增加）
        double length = BASE_LENGTH + LENGTH_INCREMENT * qAbs(deg)/10.0;
        length = qMin(length, 80.0);

        // 绘制刻度线
        QPointF leftPt(-length/2, yPos);
        QPointF rightPt(length/2, yPos);
        painter->drawLine(leftPt, rightPt);

        // 仅绘制非0刻度值
        if (deg != 0) {
            QString text = QString::number(qAbs(deg));

            // 精确计算文本位置（避免整数截断导致的跳动）
            // 左侧文本：右对齐，垂直居中
            QRectF textRectLeft = fm.boundingRect(text);
            textRectLeft.moveRight(leftPt.x() - TEXT_OFFSET);
            textRectLeft.moveTop(yPos - textRectLeft.height()/2);

            // 右侧文本：左对齐，垂直居中
            QRectF textRectRight = fm.boundingRect(text);
            textRectRight.moveLeft(rightPt.x() + TEXT_OFFSET);
            textRectRight.moveTop(yPos - textRectRight.height()/2);

            painter->drawText(textRectLeft, Qt::AlignRight | Qt::AlignVCenter, text);
            painter->drawText(textRectRight, Qt::AlignLeft | Qt::AlignVCenter, text);
        }
    }

    // 单独绘制0度地平线（红色加粗）
    if (minDeg <= 0 && maxDeg >= 0) {
        double yPos = pitchValue * DEGREES_TO_PIXELS;
        if (qAbs(yPos) <= 100) {
            pen.setColor(QColor(255, 0, 0, 150));
            pen.setWidthF(3.0);
            painter->setPen(pen);
            painter->drawLine(QPointF(-50, yPos), QPointF(50, yPos));

            // 添加中心标记（可选）
            pen.setColor(Qt::white);
            pen.setWidthF(1.0);
            painter->setPen(pen);
            painter->drawEllipse(QPointF(0, yPos), 2, 2);
        }
    }

    painter->restore();
}

void AttitudeIndicator::drawPointer(QPainter *painter)
{
    int radius = 65;
    // int radius = 70;
    painter->save();
    painter->rotate(rollValue);
    painter->setPen(Qt::NoPen);

    //指针长度
    int len = 10;
    //三角形坐标
    QPolygon pts;
    pts.setPoints(3, 0, -radius, -len / 2, -radius + len, len / 2, -radius + len);

    painter->setBrush(pointerColor);
    painter->drawConvexPolygon(pts);

    painter->restore();
}

void AttitudeIndicator::drawHandle(QPainter *painter)
{
    const double WING_LENGTH = 25.0;   // 机翼长度
    const double WING_HEIGHT = 6.0;    // 机翼高度
    const double POINT_SIZE = 3.0;     // 中心点大小

    painter->save();

    // 设置画笔
    QPen pen(handleColor);
    pen.setWidthF(2.0);
    pen.setCapStyle(Qt::RoundCap);
    pen.setJoinStyle(Qt::RoundJoin);
    painter->setPen(pen);
    painter->setBrush(handleColor);

    // 绘制左侧折线
    painter->drawLine(QPointF(-WING_LENGTH/2, 0),
                      QPointF(-WING_LENGTH/2, WING_HEIGHT));
    painter->drawLine(QPointF(-WING_LENGTH, 0),
                      QPointF(-WING_LENGTH/2, 0));

    // 绘制右侧折线
    painter->drawLine(QPointF(WING_LENGTH/2, 0),
                      QPointF(WING_LENGTH/2, WING_HEIGHT));
    painter->drawLine(QPointF(WING_LENGTH, 0),
                      QPointF(WING_LENGTH/2, 0));

    // 绘制中心点
    painter->drawEllipse(QRectF(-POINT_SIZE/2, -POINT_SIZE/2,
                                POINT_SIZE, POINT_SIZE));


    painter->restore();
}
void AttitudeIndicator::drawScaleOut(QPainter *painter)
{
    int radius = 94;
    painter->save();

    //总共8格,4格为NESW字母,4格为线条
    int steps = 8;
    double angleStep = 360.0 / steps;

    QPen pen;
    pen.setColor(foreground);
    pen.setCapStyle(Qt::RoundCap);
    pen.setWidth(4);
    painter->setPen(pen);

    //%2整数部分绘制NESW字母,其余绘制线条刻度
    for (int i = 0; i <= steps; i++) {
        painter->drawLine(0, radius - 5, 0, radius);
        painter->rotate(angleStep);
    }
    painter->rotate(45);

    pen.setWidth(2);
    painter->setPen(pen);
    for (int i = 0; i < 24; i++) {
        if (i % 3 != 0) {
            painter->drawLine(0, radius - 3, 0, radius);
        }
        painter->rotate(15);
    }

    painter->restore();
}
void AttitudeIndicator::drawScaleOutNum(QPainter *painter)
{
    const int RADIUS = 82;  // 方向标记的半径
    const int ANGLE_STEP = 45; // 角度步进

    painter->save();

    // 设置字体
    QFont font;
    font.setPixelSize(14);
    font.setBold(true);
    painter->setFont(font);
    QFontMetrics fm(font);

    // 设置画笔
    QPen pen(foreground);
    pen.setWidthF(1.5);
    painter->setPen(pen);

    // 预定义方向标记
    QMap<int, QString> directionLabels = {
        {0, "N"},   // 北
        {45, "45"},  // 东北
        {90, "E"},   // 东
        {135, "135"}, // 东南
        {180, "S"},  // 南
        {225, "225"}, // 西南
        {270, "W"},   // 西
        {315, "315"}  // 西北
    };

    // 绘制所有方向标记
    for (int angle = 0; angle < 360; angle += ANGLE_STEP) {
        if (!directionLabels.contains(angle)) continue;

        // 计算标记位置
        double radian = qDegreesToRadians((float)angle);
        double x = RADIUS * qSin(radian);
        double y = -RADIUS * qCos(radian); // 负号因为Qt坐标系Y轴向下

        // 计算文字旋转角度（使文字底部朝向圆心）
        double textAngle = angle /*+ 180*/; // 文字朝向圆心
        if (textAngle >= 360) textAngle -= 360;

        // 保存当前状态
        painter->save();

        // 移动到标记位置并旋转文字
        painter->translate(x, y);
        painter->rotate(textAngle);

        // 获取文本并计算绘制位置
        QString text = directionLabels[angle];
        QRect textRect = fm.boundingRect(text);
        textRect.moveCenter(QPoint(0, 0)); // 以原点为中心

        // 绘制文本
        painter->drawText(textRect, Qt::AlignCenter, text);

        // 恢复状态
        painter->restore();
    }

    painter->restore();
}

void AttitudeIndicator::drawPointerOut(QPainter *painter)
{
    int radius = 95;
    painter->save();
    painter->rotate(yawValue);
    painter->setPen(Qt::NoPen);

    int len = 15;
    QPolygon pts;
    pts.setPoints(3, 0, -radius, -len / 2, -radius + len, len / 2, -radius + len);

    painter->setBrush(pointerOutColor);
    painter->drawConvexPolygon(pts);
    painter->restore();
}
QColor AttitudeIndicator::getBorderOutColorStart() const
{
    return this->borderOutColorStart;
}

QColor AttitudeIndicator::getBorderOutColorEnd() const
{
    return this->borderOutColorEnd;
}

QColor AttitudeIndicator::getBorderInColorStart() const
{
    return this->borderInColorStart;
}

QColor AttitudeIndicator::getBorderInColorEnd() const
{
    return this->borderInColorEnd;
}

QColor AttitudeIndicator::getBgUpperColor() const
{
    return this->bgUpperColor;
}

QColor AttitudeIndicator::getBgLowerColor() const
{
    return this->bgLowerColor;
}

QColor AttitudeIndicator::getGlassColor() const
{
    return this->glassColor;
}

QColor AttitudeIndicator::getScaleColor() const
{
    return this->scaleColor;
}

QColor AttitudeIndicator::getLineColor() const
{
    return this->lineColor;
}

QColor AttitudeIndicator::getTextColor() const
{
    return this->textColor;
}

QColor AttitudeIndicator::getPointerColor() const
{
    return this->pointerColor;
}

QColor AttitudeIndicator::getHandleColor() const
{
    return this->handleColor;
}

float AttitudeIndicator::getRollValue() const
{
    return this->rollValue;
}

float AttitudeIndicator::getPitchValue() const
{
    return this->pitchValue;
}

float AttitudeIndicator::getYawValue() const
{
    return this->yawValue;
}
QSize AttitudeIndicator::sizeHint() const
{
    return QSize(200, 200);
}

QSize AttitudeIndicator::minimumSizeHint() const
{
    return QSize(50, 50);
}

void AttitudeIndicator::setBorderOutColorStart(const QColor &borderOutColorStart)
{
    if (this->borderOutColorStart != borderOutColorStart) {
        this->borderOutColorStart = borderOutColorStart;
        this->update();
    }
}

void AttitudeIndicator::setBorderOutColorEnd(const QColor &borderOutColorEnd)
{
    if (this->borderOutColorEnd != borderOutColorEnd) {
        this->borderOutColorEnd = borderOutColorEnd;
        this->update();
    }
}

void AttitudeIndicator::setBorderInColorStart(const QColor &borderInColorStart)
{
    if (this->borderInColorStart != borderInColorStart) {
        this->borderInColorStart = borderInColorStart;
        this->update();
    }
}

void AttitudeIndicator::setBorderInColorEnd(const QColor &borderInColorEnd)
{
    if (this->borderInColorEnd != borderInColorEnd) {
        this->borderInColorEnd = borderInColorEnd;
        this->update();
    }
}

void AttitudeIndicator::setBgUpperColor(const QColor &bgUpperColor)
{
    if (this->bgUpperColor != bgUpperColor) {
        this->bgUpperColor = bgUpperColor;
        this->update();
    }
}

void AttitudeIndicator::setBgLowerColor(const QColor &bgLowerColor)
{
    if (this->bgLowerColor != bgLowerColor) {
        this->bgLowerColor = bgLowerColor;
        this->update();
    }
}

void AttitudeIndicator::setGlassColor(const QColor &glassColor)
{
    if (this->glassColor != glassColor) {
        this->glassColor = glassColor;
        this->update();
    }
}

void AttitudeIndicator::setScaleColor(const QColor &scaleColor)
{
    if (this->scaleColor != scaleColor) {
        this->scaleColor = scaleColor;
        this->update();
    }
}

void AttitudeIndicator::setLineColor(const QColor &lineColor)
{
    if (this->lineColor != lineColor) {
        this->lineColor = lineColor;
        this->update();
    }
}

void AttitudeIndicator::setTextColor(const QColor &textColor)
{
    if (this->textColor != textColor) {
        this->textColor = textColor;
        this->update();
    }
}

void AttitudeIndicator::setPointerColor(const QColor &pointerColor)
{
    if (this->pointerColor != pointerColor) {
        this->pointerColor = pointerColor;
        this->update();
    }
}

void AttitudeIndicator::setHandleColor(const QColor &handleColor)
{
    if (this->handleColor != handleColor) {
        this->handleColor = handleColor;
        this->update();
    }
}

void AttitudeIndicator::setRollValue(float rollValue)
{
    //+-180
    if (!qFuzzyCompare(this->rollValue, rollValue) && rollValue >= -90 && rollValue <= 90) {
        this->rollValue = rollValue;
        this->update();
    }
}

void AttitudeIndicator::setPitchValue(float pitchValue)
{
    //+-100
    if (!qFuzzyCompare(this->pitchValue, pitchValue) && pitchValue >= -90 && pitchValue <= 90) {
        this->pitchValue = pitchValue;
        this->update();
    }
}
void AttitudeIndicator::setYawValue(float yawValue)
{
    if (!qFuzzyCompare(this->yawValue, yawValue)) {
        this->yawValue = yawValue;
        this->update();
    }
}

